package timing.ukulele.portal.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.common.util.TreeUtil;
import timing.ukulele.data.portal.data.SysResourceGroupTree;
import timing.ukulele.data.portal.view.SysResourceGroupVO;
import timing.ukulele.data.portal.view.SysResourceVO;
import timing.ukulele.facade.portal.mvc.SysResourceControllerFacade;
import timing.ukulele.portal.convertor.ResourceConvertor;
import timing.ukulele.portal.convertor.ResourceGroupConvertor;
import timing.ukulele.portal.dictionary.ResourceMethodEnum;
import timing.ukulele.portal.persistent.SysResource;
import timing.ukulele.portal.persistent.SysResourceGroup;
import timing.ukulele.portal.service.SysResourceGroupService;
import timing.ukulele.portal.service.SysResourceService;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
public class SysResourceController implements SysResourceControllerFacade {
    private final SysResourceService service;
    private final SysResourceGroupService groupService;

    public SysResourceController(SysResourceService service, SysResourceGroupService groupService) {
        this.service = service;
        this.groupService = groupService;
    }

    @Override
    public ResponseData<SysResourceVO> resource(Long id) {
        SysResource po = this.service.getById(id);
        if (po != null) {
            SysResourceVO vo = ResourceConvertor.INSTANCE.p2v(po);
            return ResponseData.success(vo);
        }
        return ResponseData.success();
    }

    @Override
    public ResponseData<Boolean> add(String currentUser, SysResourceVO vo) {
        if (vo == null || vo.getGroupId() == null
                || !StringUtils.hasText(vo.getResource())) {
            return ResponseData.paramError();
        }
        if (!StringUtils.hasText(vo.getResource()) || !ResourceMethodEnum.hasValue(vo.getMethod())) {
            return ResponseData.paramError();
        }
        SysResource po = ResourceConvertor.INSTANCE.v2p(vo);
        this.service.save(po);
        return ResponseData.success();
    }

    @Override
    public ResponseData<Boolean> edit(String currentUser, SysResourceVO vo) {
        if (vo == null || vo.getGroupId() == null
                || !StringUtils.hasText(vo.getResource())) {
            return ResponseData.paramError();
        }
        if (!ResourceMethodEnum.hasValue(vo.getMethod())) {
            return ResponseData.paramError();
        }
        SysResource po = ResourceConvertor.INSTANCE.v2p(vo);
        this.service.updateById(po);
        return ResponseData.success();
    }

    @Override
    public ResponseData<Boolean> delete(String currentUser, Long id) {
        this.service.lambdaUpdate()
                .set(SysResource::getDeleted, Boolean.TRUE)
                .set(SysResource::getUpdateBy, currentUser)
                .eq(SysResource::getId, id)
                .update();
        return ResponseData.success();
    }


    @GetMapping("/page/{current}/{size}")
    public ResponseData<IPage<SysResourceVO>> getPage(@PathVariable(name = "current") int current,
                                                      @PathVariable(value = "size") int size,
                                                      @RequestParam(value = "groupId", required = false) Long groupId,
                                                      @RequestParam(value = "name", required = false) String resource,
                                                      @RequestParam(value = "remark", required = false) String remark,
                                                      @RequestParam(value = "method", required = false) String method,
                                                      @RequestParam(value = "deleted", required = false) Boolean deleted) {
        if (size == 0) {
            size = 10;
        }
        if (current == 0) {
            current = 1;
        }
        return ResponseData.success(this.service.getPage(groupId, resource, remark, method, deleted, current, size));
    }

    @Override
    public ResponseData<List<SysResourceGroupVO>> getGroupAll(Boolean deleted) {
        LambdaQueryChainWrapper<SysResourceGroup> query = this.groupService.lambdaQuery();
        if (deleted != null)
            query.eq(SysResourceGroup::getDeleted, deleted);
        List<SysResourceGroup> list = query.list();
        if (CollectionUtils.isEmpty(list)) {
            return ResponseData.success();
        }
        List<SysResourceGroupVO> voList = ResourceGroupConvertor.INSTANCE.p2vList(list);
        return ResponseData.success(voList);
    }

    @Override
    public ResponseData<List<SysResourceGroupTree>> tree(Boolean deleted) {
        LambdaQueryChainWrapper<SysResourceGroup> query = this.groupService.lambdaQuery();
        if (deleted != null)
            query.eq(SysResourceGroup::getDeleted, deleted);
        List<SysResourceGroup> list = query.list();
        if (CollectionUtils.isEmpty(list)) {
            return ResponseData.success();
        }
        List<SysResourceGroupTree> treeList = new ArrayList<>();
        for (SysResourceGroup group : list) {
            SysResourceGroupTree node = new SysResourceGroupTree();
            SysResourceGroupVO vo = ResourceGroupConvertor.INSTANCE.p2v(group);
            node.setId(group.getId());
            node.setKey(group.getId() + "");
            node.setParentId(group.getParentId());
            node.setTitle(group.getName());
            node.setGroup(vo);
            treeList.add(node);
        }
        List<SysResourceGroupTree> tree = TreeUtil.buildByRecursive(treeList, 0L);
        return ResponseData.success(tree);
    }

    @Override
    public ResponseData<SysResourceGroupVO> getGroup(Long id) {
        SysResourceGroup po = this.groupService.getById(id);
        if (po != null) {
            SysResourceGroupVO vo = ResourceGroupConvertor.INSTANCE.p2v(po);
            return ResponseData.success(vo);
        }
        return ResponseData.success();
    }

    @Override
    public ResponseData<Boolean> addGroup(String currentUser, SysResourceGroupVO vo) {
        if (vo == null || !StringUtils.hasText(vo.getName()) || vo.getId() != null) {
            return ResponseData.paramError();
        }
        SysResourceGroup po = ResourceGroupConvertor.INSTANCE.v2p(vo);
        this.groupService.save(po);
        return ResponseData.success(Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> editGroup(String currentUser, SysResourceGroupVO vo) {
        if (vo == null || !StringUtils.hasText(vo.getName()) || vo.getId() == null) {
            return ResponseData.paramError();
        }
        SysResourceGroup po = ResourceGroupConvertor.INSTANCE.v2p(vo);
        this.groupService.updateById(po);
        return ResponseData.success(Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> disableGroup(String currentUser, Long groupId) {
        this.groupService.lambdaUpdate().set(SysResourceGroup::getDeleted, Boolean.TRUE)
                .set(SysResourceGroup::getUpdateBy, currentUser)
                .set(SysResourceGroup::getUpdateTime, new Date())
                .eq(SysResourceGroup::getId, groupId)
                .update();
        return ResponseData.success(Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> enableGroup(String currentUser, Long groupId) {
        this.groupService.lambdaUpdate().set(SysResourceGroup::getDeleted, Boolean.FALSE)
                .set(SysResourceGroup::getUpdateBy, currentUser)
                .set(SysResourceGroup::getUpdateTime, new Date())
                .eq(SysResourceGroup::getId, groupId)
                .update();
        return ResponseData.success(Boolean.TRUE);
    }
}
